/**
 * @file         cm_demo_audio.c
 * @brief        AUDIO接口
 * @copyright    Copyright © 2021 China Mobile IOT. All rights reserved.
 * @author       WangPeng
 * @date         2021/04/20
 *
 */
#include "cm_demo_audio.h"
#include "cm_audio_player.h"
#include "cm_audio_recorder.h"
#include "cm_sys.h"
#include "cm_fs.h"
#include "test_audio.h"

#define TEST_MP3_FILE_PATH "test.mp3"
#define TEST_AMR_FILE_PATH "test.amr"


#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))

//内置用于播放的默认PCM音频数据
extern unsigned char pcm_alarm[5760];

//内置用于播放的默认MP3音频数据
extern unsigned char mp3_test[5296];

//内置用于播放的默认AMR音频数据
extern const unsigned char amr_test[3302];


#define AUDIO_TEST_FRAME_BUFFER_SIZE (320 * 50)

static uint8_t u8BufferFrames[AUDIO_TEST_FRAME_BUFFER_SIZE] = "";      //存储录音数据
static uint8_t u8BufferFrames_2[AUDIO_TEST_FRAME_BUFFER_SIZE] = "";
static uint32_t u32BufferFramesLength = 0;                          //录制的音频数据长度
static uint32_t u32BufferFramesLength_2 = 0;
static uint32_t count = 0;
//播放回调函数
static void __cm_player_process_event(cm_audio_play_event_e event, void *param)
{
    if (event == CM_AUDIO_PLAY_EVENT_FINISHED)                      //判断播放结束
    {
        /* 通知事件为中断触发，不可阻塞，不可做耗时较长的操作，例如不可使用UART打印log */
        //todo
    }
}

//录音回调函数，Demo实现将录音数据存入内存，可供播放，pu8Frames为录音的音频数据，length为该数据的长度
static void __cm_record_cb(cm_audio_record_event_e event, void *param)
{
    /* 通知事件为中断触发，不可阻塞，不可做耗时较长的操作，例如不可使用UART打印log */

    cm_audio_record_data_t *record_data = (cm_audio_record_data_t *)param;

    if (CM_AUDIO_RECORD_EVENT_DATA == event)
    {
        int32_t len = record_data->len;

        if (AUDIO_TEST_FRAME_BUFFER_SIZE > (len + u32BufferFramesLength)) {    
            memcpy (u8BufferFrames + u32BufferFramesLength, record_data->data, len);     //录音数据存储于数组中 
            u32BufferFramesLength += len;                     //录制的音频数据长度+length               
        }
        else{
                memcpy(u8BufferFrames_2,u8BufferFrames,u32BufferFramesLength);
                u32BufferFramesLength_2 = u32BufferFramesLength;
                u32BufferFramesLength = 0;
                cm_demo_printf("record count:%u\n",count++);
                // cm_audio_sample_param_t frame = {.sample_format = CM_AUDIO_SAMPLE_FORMAT_16BIT, .rate = CM_AUDIO_SAMPLE_RATE_8000HZ, .num_channels = CM_AUDIO_SOUND_MONO};
                // cm_audio_player_stream_open(CM_AUDIO_PLAY_FORMAT_PCM, &frame);
                
                //cm_audio_player_stream_open(CM_AUDIO_PLAY_FORMAT_AMRNB, NULL);

                //cm_audio_player_stream_push(u8BufferFrames_2, u32BufferFramesLength_2);
        }
    }
}


/**
 *  UART口音频功能调试使用示例
 *  CM:AUDIO_PLAY:VOLSET:5               //设置音量为5
 *  CM:AUDIO_PLAY:VOLGET                 //查询当前音量设置值
 *  CM:AUDIO_PLAY:STOP                   //停止播放
 *  CM:AUDIO_PLAY:PAUSE                  //暂停播放
 *  CM:AUDIO_PLAY:RESUME                 //继续播放
 *  CM:AUDIO_PLAY:FILEMP3                //播放示例中内置的MP3文件
 *  CM:AUDIO_PLAY:FILEAMR                //播放示例中内置的AMR文件
 *  CM:AUDIO_PLAY:STARTSTREAM            //流播放开启
 *  CM:AUDIO_PLAY:STOPSTREAM             //流播放关闭
 *  CM:AUDIO_PLAY:STREAMFRAME            //传输流播放的音频数据
 *  CM:AUDIO_PLAY:FILE                   //将音频数据写入至文件系统中（写入后可使用cm_audio_play_file()做测试）
 */
/**
 *  UART口音频功能调试使用示例
 *  CM:AUDIO_RECORD:PCMSTART                //开始录制PCM（最多5秒）
 *  CM:AUDIO_RECORD:AMR475START             //开始录制AMR475
 *  CM:AUDIO_RECORD:AMR515START             //开始录制AMR515
 *  CM:AUDIO_RECORD:AMR590START             //开始录制AMR590
 *  CM:AUDIO_RECORD:AMR670START             //开始录制AMR670
 *  CM:AUDIO_RECORD:AMR740START             //开始录制AMR740
 *  CM:AUDIO_RECORD:AMR795START             //开始录制AMR795
 *  CM:AUDIO_RECORD:AMR1020START            //开始录制AMR1020
 *  CM:AUDIO_RECORD:AMR1220START            //开始录制AMR1220
 *  CM:AUDIO_RECORD:STOP                    //结束录音
 *  CM:AUDIO_RECORD:STARTSTREAMPCM          //PCM流播放开启，用于播放录制的PCM数据
 *  CM:AUDIO_RECORD:STARTSTREAMAMR          //AMR流播放开启，用于播放录制的AMR数据
 *  CM:AUDIO_RECORD:STOPSTREAM              //流播放关闭
 *  CM:AUDIO_RECORD:STREAMFRAME             //传输流播放的音频数据，即录制的音频数据
 */
void cm_test_audio_operation(unsigned char *cmd[],int len)
{
    if (0 == strcmp(cmd[2],"PLAY"))
    {
        unsigned char operation[20] = {0};
        sprintf(operation, "%s", cmd[3]);
        int param = 0;
        static int vol = -1;
        static int cha = -1;
        if (0 == strcmp(operation, "VOLSET"))           //设置音量，范围0~100，CM:AUDIO_PLAY:VOLSET:5
        {
            param = atoi(cmd[4]);
            
            vol = param;
            int32_t set_cfg = cm_audio_play_set_cfg(CM_AUDIO_PLAY_CFG_VOLUME, &param);
            cm_demo_printf("cm_audio_play_set_cfg ret:%d\n",set_cfg);               //音量设置   
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,set_cfg,cm_audio_play_set_cfg);
        }
        else if (0 == strcmp(operation, "CHASET"))           //设置通道，暂不支持
        {
            param = atoi(cmd[4]);
            
            cha = param;
            int32_t set_cfg = cm_audio_play_set_cfg(CM_AUDIO_PLAY_CFG_CHANNEL, &param);
            cm_demo_printf("cm_audio_play_set_cfg ret:%d\n",set_cfg);                 //音量设置   
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,set_cfg,cm_audio_play_set_cfg);
        }
        else if (0 == strcmp(operation, "CHAGET"))           //查询通道设置值
        {
            int32_t get_cfg = cm_audio_play_get_cfg(CM_AUDIO_PLAY_CFG_CHANNEL, &param);
            cm_demo_printf("cm_audio_play_get_cfg ret:%d\n",get_cfg); 
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,get_cfg,cm_audio_play_get_cfg);
            cm_demo_printf("[AUDIO] channel:%d\n", param); 
            OCTEST_EXPECT_EQUAL_INT32(cha,param); 
        }
        else if (0 == strcmp(operation, "VOLGET"))      //查询音量设置值，CM:AUDIO_PLAY:VOLGET
        {
            int32_t get_cfg = cm_audio_play_get_cfg(CM_AUDIO_PLAY_CFG_VOLUME, &param);
            //打印查询到的音量设置值 
            cm_demo_printf("cm_audio_play_get_cfg ret:%d\n",get_cfg);
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,get_cfg,cm_audio_play_get_cfg);
            cm_demo_printf("[AUDIO] volume:%d\n", param); 
            OCTEST_EXPECT_EQUAL_INT32(vol,param);       
        }
        else if (0 == strcmp(operation, "PAUSE"))       //暂停播放，CM:AUDIO_PLAY:PAUSE
        {
            int32_t pause = cm_audio_player_pause();
            cm_demo_printf("cm_audio_player_pause ret:%d\n",pause);
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,pause,cm_audio_player_pause);
        }
        else if (0 == strcmp(operation, "RESUME"))      //继续播放，CM:AUDIO_PLAY:RESUME
        {
            int32_t resume = cm_audio_player_resume();
            cm_demo_printf("cm_audio_player_resume ret:%d\n",resume);
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,resume,cm_audio_player_resume);
        }
        else if (0 == strcmp(operation, "STOP"))        //结束播放，CM:AUDIO_PLAY:STOP 
        {
            int32_t stop = cm_audio_player_stop();
            cm_demo_printf("cm_audio_player_stop ret:%d\n",stop);
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,stop,cm_audio_player_stop);
        }
        else if (0 == strcmp(operation, "FILEMP3"))   //播报内置的MP3文件，CM:AUDIO_PLAY:FILEMP3
        {
            int32_t play_file = cm_audio_play_file(TEST_MP3_FILE_PATH, CM_AUDIO_PLAY_FORMAT_MP3, NULL, __cm_player_process_event, "FILEMP3");
            cm_demo_printf("cm_audio_play_file ret:%d\n",play_file);
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,play_file,cm_audio_play_file);
        }   
        else if (0 == strcmp(operation, "FILEAMR"))   //播报内置的AMR文件，CM:AUDIO_PLAY:FILEAMR
        {
            int32_t play_file = cm_audio_play_file(TEST_AMR_FILE_PATH, CM_AUDIO_PLAY_FORMAT_AMRNB, NULL, __cm_player_process_event, "FILEAMR");
            cm_demo_printf("cm_audio_play_file ret:%d\n",play_file);
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,play_file,cm_audio_play_file);
        }
        else if(0 == strcmp(operation, "STARTSTREAM"))
        {
            cm_audio_sample_param_t frame = {.sample_format = CM_AUDIO_SAMPLE_FORMAT_16BIT, .rate = CM_AUDIO_SAMPLE_RATE_8000HZ, .num_channels = CM_AUDIO_SOUND_MONO};
            int32_t stream_open = cm_audio_player_stream_open(CM_AUDIO_PLAY_FORMAT_PCM, &frame);
            cm_demo_printf("cm_audio_player_stream_open ret:%d\n",stream_open);              //从pipe中播放音频（开启）
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,stream_open,cm_audio_player_stream_open);
        }
        else if(0 == strcmp(operation, "STOPSTREAM"))
        {
            cm_audio_player_stream_close();               //pipe中播放音频（关闭）
        }
        else if(0 == strcmp(operation, "STREAMFRAME"))
        {
            int32_t stream_push = cm_audio_player_stream_push(pcm_alarm, ARRAY_SIZE(pcm_alarm));
            cm_demo_printf("cm_audio_player_stream_push ret:%d\n",stream_push);      //往pipe中发送要播放的PCM数据
            OCTEST_FUNC_EXPECT_GREATER_OR_EQUAL_INT32(0,stream_push,cm_audio_player_stream_push);
        }
        else if(0 == strcmp(operation, "FILE"))
        {
            int32_t fd = cm_fs_open(TEST_MP3_FILE_PATH, CM_FS_WB);
            cm_fs_write(fd, mp3_test, ARRAY_SIZE(mp3_test));
            cm_fs_close(fd);

            fd = cm_fs_open(TEST_AMR_FILE_PATH, CM_FS_WB);
            cm_fs_write(fd, amr_test, ARRAY_SIZE(amr_test));
            cm_fs_close(fd);
        }
        else
        {
            cm_demo_printf("param error!\n"); 
        }
        return;
    }else if(0 == strcmp(cmd[2],"RECORDER"))
    {
        unsigned char operation[20] = {0};
        sprintf(operation, "%s", cmd[3]);
        int param = 0;
        static int record_ch = -1;
        static int record_gain = -1;
        if (0 == strcmp(operation, "PCMSTART")) //开始录音，需配合结束录音指令使用，CM:AUDIO_RECORD:PCMSTART 
        {
            //录音数据存放数组的长度清零
            u32BufferFramesLength = 0;
            cm_audio_sample_param_t frame = {.sample_format = CM_AUDIO_SAMPLE_FORMAT_16BIT, .rate = CM_AUDIO_SAMPLE_RATE_8000HZ, .num_channels = CM_AUDIO_SOUND_MONO};
            int32_t recorder_start = cm_audio_recorder_start(CM_AUDIO_RECORD_FORMAT_PCM, &frame, (cm_audio_record_callback_t)__cm_record_cb, "PCM");
            cm_demo_printf("cm_audio_recorder_start ret:%d\n",recorder_start);        //_cm_record_cb 为录音回调函数，客户执行相应操作
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,recorder_start,cm_audio_recorder_start);
            cm_demo_printf("[AUDIO] record start\n");
        }
        else if(0 == strcmp(operation, "SET_RECORD_CH"))
        {
            record_ch = atoi(cmd[4]);
            int32_t record_set_cfg = cm_audio_record_set_cfg(CM_AUDIO_RECORD_CFG_CHANNEL, &record_ch);
            cm_demo_printf("cm_audio_record_set_cfg ret:%d", record_set_cfg);
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,record_set_cfg,cm_audio_record_set_cfg);
        }
        else if(0 == strcmp(operation, "GET_RECORD_CH"))
        {
            int value = -1;
            int32_t record_get_cfg = cm_audio_record_get_cfg(CM_AUDIO_RECORD_CFG_CHANNEL, &value);
            cm_demo_printf("cm_audio_record_get_cfg ret:%d", record_get_cfg);
            cm_demo_printf("record channel:%d\n",value);
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,record_get_cfg,cm_audio_record_get_cfg);
            OCTEST_EXPECT_EQUAL_INT32(record_ch,value);
        }
        else if(0 == strcmp(operation, "SET_RECORD_GAIN"))
        {
            record_gain =atoi(cmd[4]);
            int record_set_cfg = cm_audio_record_set_cfg(CM_AUDIO_RECORD_CFG_GAIN, &record_gain);
            cm_demo_printf("cm_audio_record_set_cfg ret:%d", record_set_cfg);
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,record_set_cfg,cm_audio_record_set_cfg);
        }
        else if(0 == strcmp(operation, "GET_RECORD_GAIN"))
        {
            int value = -1;
            int32_t record_get_cfg = cm_audio_record_get_cfg(CM_AUDIO_RECORD_CFG_GAIN, &value);
            cm_demo_printf("cm_audio_record_get_cfg ret:%d", record_get_cfg);
            cm_demo_printf("record channel:%d\n",value);
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,record_get_cfg,cm_audio_record_get_cfg);
            OCTEST_EXPECT_EQUAL_INT32(record_gain,value);
        }
        else if (0 == strcmp(operation, "STOP"))   //结束录音，需配合开始录音指令使用，CM:AUDIO_RECORD:STOP
        {
            //结束录音
            cm_audio_recorder_stop();
            cm_demo_printf("[AUDIO] record end\n");
        }
        else if (0 == strcmp(operation, "AMR475START")) //开始录音，需配合结束录音指令使用，CM:AUDIO_RECORD:AMR475START
        {
            //录音数据存放数组的长度清零
            u32BufferFramesLength = 0;
            int32_t recorder_start = cm_audio_recorder_start(CM_AUDIO_RECORD_FORMAT_AMRNB_475, NULL, (cm_audio_record_callback_t)__cm_record_cb, "475");
            cm_demo_printf("cm_audio_recorder_start ret:%d\n",recorder_start);        //_cm_record_cb 为录音回调函数，客户执行相应操作
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,recorder_start,cm_audio_recorder_start);
            cm_demo_printf("[AUDIO] record start\n");
        }
        else if (0 == strcmp(operation, "AMR515START")) //开始录音，需配合结束录音指令使用，CM:AUDIO_RECORD:AMR515START
        {
            //录音数据存放数组的长度清零
            u32BufferFramesLength = 0;
            int32_t recorder_start = cm_audio_recorder_start(CM_AUDIO_RECORD_FORMAT_AMRNB_515, NULL, (cm_audio_record_callback_t)__cm_record_cb, "515");
            cm_demo_printf("cm_audio_recorder_start ret:%d\n",recorder_start);        //_cm_record_cb 为录音回调函数，客户执行相应操作
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,recorder_start,cm_audio_recorder_start);
            cm_demo_printf("[AUDIO] record start\n");
        }
        else if (0 == strcmp(operation, "AMR590START")) //开始录音，需配合结束录音指令使用，CM:AUDIO_RECORD:AMR590START
        {
            //录音数据存放数组的长度清零
            u32BufferFramesLength = 0;
            int32_t recorder_start = cm_audio_recorder_start(CM_AUDIO_RECORD_FORMAT_AMRNB_590, NULL, (cm_audio_record_callback_t)__cm_record_cb, "590");
            cm_demo_printf("cm_audio_recorder_start ret:%d\n",recorder_start);        //_cm_record_cb 为录音回调函数，客户执行相应操作
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,recorder_start,cm_audio_recorder_start);
            cm_demo_printf("[AUDIO] record start\n");
        }
        else if (0 == strcmp(operation, "AMR670START")) //开始录音，需配合结束录音指令使用，CM:AUDIO_RECORD:AMR670START
        {
            //录音数据存放数组的长度清零
            u32BufferFramesLength = 0;
            int32_t recorder_start = cm_audio_recorder_start(CM_AUDIO_RECORD_FORMAT_AMRNB_670, NULL, (cm_audio_record_callback_t)__cm_record_cb, "670");
            cm_demo_printf("cm_audio_recorder_start ret:%d\n",recorder_start);        //_cm_record_cb 为录音回调函数，客户执行相应操作
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,recorder_start,cm_audio_recorder_start);
            cm_demo_printf("[AUDIO] record start\n");
        }
        else if (0 == strcmp(operation, "AMR740START")) //开始录音，需配合结束录音指令使用，CM:AUDIO_RECORD:AMR740START
        {
            //录音数据存放数组的长度清零
            u32BufferFramesLength = 0;
            int32_t recorder_start = cm_audio_recorder_start(CM_AUDIO_RECORD_FORMAT_AMRNB_740, NULL, (cm_audio_record_callback_t)__cm_record_cb, "740");
            cm_demo_printf("cm_audio_recorder_start ret:%d\n",recorder_start);        //_cm_record_cb 为录音回调函数，客户执行相应操作
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,recorder_start,cm_audio_recorder_start);
            cm_demo_printf("[AUDIO] record start\n");
        }
        else if (0 == strcmp(operation, "AMR795START")) //开始录音，需配合结束录音指令使用，CM:AUDIO_RECORD:AMR795START
        {
            //录音数据存放数组的长度清零
            u32BufferFramesLength = 0;
            int32_t recorder_start = cm_audio_recorder_start(CM_AUDIO_RECORD_FORMAT_AMRNB_795, NULL, (cm_audio_record_callback_t)__cm_record_cb, "795");
            cm_demo_printf("cm_audio_recorder_start ret:%d\n",recorder_start);        //_cm_record_cb 为录音回调函数，客户执行相应操作
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,recorder_start,cm_audio_recorder_start);
            cm_demo_printf("[AUDIO] record start\n");
        }
        else if (0 == strcmp(operation, "AMR1020START")) //开始录音，需配合结束录音指令使用，CM:AUDIO_RECORD:AMR1020START
        {
            //录音数据存放数组的长度清零
            u32BufferFramesLength = 0;
            int32_t recorder_start = cm_audio_recorder_start(CM_AUDIO_RECORD_FORMAT_AMRNB_1020, NULL, (cm_audio_record_callback_t)__cm_record_cb, "1020");
            cm_demo_printf("cm_audio_recorder_start ret:%d\n",recorder_start);        //_cm_record_cb 为录音回调函数，客户执行相应操作
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,recorder_start,cm_audio_recorder_start);
            cm_demo_printf("[AUDIO] record start\n");
        }
        else if (0 == strcmp(operation, "AMR1220START")) //开始录音，需配合结束录音指令使用，CM:AUDIO_RECORD:AMR1220START
        {
            //录音数据存放数组的长度清零
            u32BufferFramesLength = 0;
            int32_t recorder_start = cm_audio_recorder_start(CM_AUDIO_RECORD_FORMAT_AMRNB_1220, NULL, (cm_audio_record_callback_t)__cm_record_cb, "1120");
            cm_demo_printf("cm_audio_recorder_start ret:%d\n",recorder_start);        //_cm_record_cb 为录音回调函数，客户执行相应操作
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,recorder_start,cm_audio_recorder_start);
            cm_demo_printf("[AUDIO] record start\n");
        }
        else if(0 == strcmp(operation, "STARTSTREAMPCM"))
        {
            cm_audio_sample_param_t frame = {.sample_format = CM_AUDIO_SAMPLE_FORMAT_16BIT, .rate = CM_AUDIO_SAMPLE_RATE_8000HZ, .num_channels = CM_AUDIO_SOUND_MONO};
            int32_t stream_open = cm_audio_player_stream_open(CM_AUDIO_PLAY_FORMAT_PCM, &frame);
            cm_demo_printf("cm_audio_player_stream_open ret:%d\n",stream_open);
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,stream_open,cm_audio_player_stream_open);
        }
        else if(0 == strcmp(operation, "STARTSTREAMAMR"))
        {
            int32_t stream_open = cm_audio_player_stream_open(CM_AUDIO_PLAY_FORMAT_AMRNB, NULL);
            cm_demo_printf("cm_audio_player_stream_open ret:%d\n",stream_open);
            OCTEST_FUNC_EXPECT_EQUAL_INT32(0,stream_open,cm_audio_player_stream_open);
        }
        else if(0 == strcmp(operation, "STOPSTREAM"))
        {
            cm_audio_player_stream_close();
        }
        else if(0 == strcmp(operation, "STREAMFRAME"))
        {
            int32_t stream_push = cm_audio_player_stream_push(u8BufferFrames_2, u32BufferFramesLength_2);
            cm_demo_printf("cm_audio_player_stream_push ret:%d\n",stream_push);
            OCTEST_FUNC_EXPECT_GREATER_OR_EQUAL_INT32(0,stream_push,cm_audio_player_stream_push);
        }
        else
        {
            cm_demo_printf("[AUDIO] Illegal operation\n"); 
        }
        return;
    }
}
